package cz.cvut.fel.gfupan.gui.component;

import cz.cvut.fel.gfupan.gui.Session;
import cz.cvut.fel.gfupan.gui.action.InputKeyListener;
import cz.cvut.fel.gfupan.gui.action.TextFocusListener;
import cz.cvut.fel.gfupan.gui.execution.Executable;
import cz.cvut.fel.gfupan.gui.tab.AbstractTab;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

public class TextField extends JTextField implements TextComponent, Observable, Observer {

    private List<Observer> observers;
    private Executable exec;

    public TextField(AbstractTab tab, Observer... obs) {
        this.observers = new ArrayList<Observer>();

        if (obs != null && obs.length > 0) {
            observers.addAll(Arrays.asList(obs));
        }
        this.addFocusListener(new TextFocusListener(this, tab));
        this.addKeyListener(new InputKeyListener(tab));

        this.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent de) {
                updateObservers();
            }

            @Override
            public void removeUpdate(DocumentEvent de) {
                updateObservers();
            }

            @Override
            public void changedUpdate(DocumentEvent de) {
                updateObservers();
            }

            private void updateObservers() {
                notifyObservers();
            }
        });
    }

    @Override
    public void setText(String text) {
        if (!getText().equals(text)) {
            Session.getInstance().hasChanged();
        }
        super.setText(text);
    }

    @Override
    public void clear() {
        this.setText("");
        Session.getInstance().notChanged();
    }

    @Override
    public void addObserver(Observer o) {
        observers.add(o);
    }

    @Override
    public void notifyObservers() {
        for (Observer o : observers) {
            o.inform();
        }
    }

    @Override
    public void inform() {
        if (exec != null) {
            this.setText(exec.execute());
        }
    }

    @Override
    public void setExecutor(Executable e) {
        this.exec = e;
    }
}
